/**
 * 
 */
package com.platform.common.utils;

import java.security.SecureRandom;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;

/**
 * <pre>
 * 功能：封装各种生成唯一性ID算法的工具类
 * </pre>
 * 
 * @author wei.gao
 */
public class IdentitiesUtils {
	
	private static SecureRandom random = new SecureRandom();
	private static AtomicLong atomicLongID = new AtomicLong(10000L);
	
	/**
	 * <pre>
	 * 功能：封装JDK自带的UUID, 通过Random数字生成, 中间有-分割.
	 * </pre>
	 * 
	 * @return
	 */
	public static String uuid() {
		return UUID.randomUUID().toString();
	}
	
	/**
	 * <pre>
	 * 功能：封装JDK自带的UUID, 通过Random数字生成, 中间无-分割.
	 * </pre>
	 * 
	 * @return
	 */
	public static String uuid2() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}
	
	/**
	 * <pre>
	 * 功能：使用SecureRandom随机生成Long.
	 * </pre>
	 * 
	 * @return
	 */
	public static long randomLong() {
		return Math.abs(random.nextLong());
	}
	
	/**
	 * <pre>
	 * 功能：主要用于数据库的主键，方便基于时间点的跨数据库的异步数据同步。
	 * 前半部分是currentTimeMillis，后半部分是nanoTime（正数）补齐20位的字符串
	 * 如果通过System.nanoTime()获取的是负数，则通过nanoTime = nanoTime+Long.MAX_VALUE+1
	 * </pre>
	 * 
	 * @return 形如 yyyyMMddHHmmssSSSZ000001955819583229710000
	 * 的(42位)保证唯一的递增的序列号字符串
	 */
	public static String getTimeMillisSequence() {
		long nanoTime = System.nanoTime();
		String preFix = null;
		if (nanoTime < 0) {
			//负数补位A保证负数排在正数Z前面,解决正负临界值(如A9223372036854775807至Z0000000000000000000)问题。
			preFix = "A";
			nanoTime = nanoTime + Long.MAX_VALUE + 1;
		} else {
			preFix = "Z";
		}
		String nanoTimeStr = String.valueOf(nanoTime);
		int difBit = String.valueOf(Long.MAX_VALUE).length() - nanoTimeStr.length();
		for (int i = 0; i < difBit; i++) {
			preFix = StringUtils.concat(preFix, "0");
		}
		long last = atomicLongID.getAndIncrement() % 10000 + 10000;
		return StringUtils.concat(DateUtils.format(new Date(), "yyyyMMddHHmmssSSS"), preFix, nanoTimeStr, last);
	}
}
